﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Battle.View
{
    public class BufferResourceCache : MonoBehaviour
    {
        Dictionary<string, int> loadedParticleCounter = new Dictionary<string, int>();
        Dictionary<string, int> loadingParticleCounter = new Dictionary<string, int>();

        public void AddBuffer(string buffId)
        {
            foreach(var particleId in GetBufferParticles(buffId))
            {
                AddBuffParticle(particleId);
            }
        }

        public void RemoveBuffer(string buffId)
        {
            foreach (var particleId in GetBufferParticles(buffId))
            {
                RemoveBuffParticle(particleId);
            }
        }

        public bool IsBufferLoaded(string buffId)
        {
            foreach (var particleId in GetBufferParticles(buffId))
            {
                if (loadedParticleCounter.ContainsKey(particleId) && loadedParticleCounter[particleId] > 0)
                {

                }
                else
                {
                    return false;
                }
            }
            return true;
        }


        public List<string> GetBufferParticles(string buffId)
        {
            List<string> particleIds = new List<string>();
            var dictBuff = Dict.Blo.DictBuffBlo.GetTableBuff(buffId);
            if (dictBuff != null)
            {
                if (!string.IsNullOrEmpty(dictBuff.EffectOn) && !string.IsNullOrEmpty(dictBuff.EffectOnBone))
                {
                    particleIds.Add(dictBuff.EffectOn);
                }
                if (!string.IsNullOrEmpty(dictBuff.EffectOff) && !string.IsNullOrEmpty(dictBuff.EffectOffBone))
                {
                    particleIds.Add(dictBuff.EffectOff);
                }
                if (!string.IsNullOrEmpty(dictBuff.HitEffect) && !string.IsNullOrEmpty(dictBuff.HitEffectBone))
                {
                    particleIds.Add(dictBuff.HitEffect);
                }
                if (!string.IsNullOrEmpty(dictBuff.LastEffect) && !string.IsNullOrEmpty(dictBuff.LastEffectBone))
                {
                    particleIds.Add(dictBuff.LastEffect);
                }
            }
            return particleIds;
        }


        void AddBuffParticle(string particleId, int num = 1)
        {
            if (loadedParticleCounter.ContainsKey(particleId))
            {
                loadedParticleCounter[particleId] += num;
            }
            else
            {
                if (loadingParticleCounter.ContainsKey(particleId))
                {
                    loadingParticleCounter[particleId]++;
                }
                else
                {
                    loadingParticleCounter[particleId] = num;
                    StartCoroutine(LoadParticle(particleId));
                }
            }
        }

        void RemoveBuffParticle(string particleId, int num = 1)
        {
            if (loadedParticleCounter.ContainsKey(particleId))
            {
                loadedParticleCounter[particleId] -= num;
                if (loadedParticleCounter[particleId] <= 0)
                {
                    UnloadParticle(particleId);
                    loadedParticleCounter.Remove(particleId);
                }
            }
            else
            {
                if (loadingParticleCounter.ContainsKey(particleId))
                {
                    loadingParticleCounter[particleId] -= num;
                }
            }
        }


        IEnumerator LoadParticle(string particleId)
        {
            var dp = Dict.Blo.DictParticleBlo.GetParticle(particleId);
            if (dp != null)
            {
                string assetbundleName = "particles/" + dp.ResourcePath;
                string assetName = CommonMethod.GetAssetNameFromAssetBundleName(assetbundleName);
                AssetLoad.AssetBundleManager.Instance.LoadAssetBundle(assetbundleName);
                while (!AssetLoad.AssetBundleManager.Instance.IsLoadedAssetBundle(assetbundleName))
                {
                    yield return null;
                }
                GameObjectPoolManager.Instance.Regist(assetbundleName, assetName);
                if (!loadingParticleCounter.ContainsKey(particleId) ||
                    (loadingParticleCounter.ContainsKey(particleId) && loadingParticleCounter[particleId] <= 0))
                {
                    GameObjectPoolManager.Instance.UnRegist(assetbundleName, assetName);
                    AssetLoad.AssetBundleManager.Instance.UnloadAssetBundle(assetbundleName);
                    yield break;
                }
                else
                {
                    if (loadedParticleCounter.ContainsKey(particleId))
                    {
                        loadedParticleCounter[particleId] += loadingParticleCounter[particleId];
                    }
                    else
                    {
                        loadedParticleCounter[particleId] = loadingParticleCounter[particleId];
                    }
                    loadingParticleCounter.Remove(particleId);
                }
            }
        }

        void UnloadParticle(string particleId)
        {
            var dp = Dict.Blo.DictParticleBlo.GetParticle(particleId);
            if (dp != null)
            {
                string assetbundleName = "particles/" + dp.ResourcePath;
                string assetName = CommonMethod.GetAssetNameFromAssetBundleName(assetbundleName);
                AssetLoad.AssetBundleManager.Instance.UnloadAssetBundle(assetbundleName);
                GameObjectPoolManager.Instance.UnRegist(assetbundleName, assetName);
            }
        }


        public static BufferResourceCache Initialize()
        {
            GameObject obj = new GameObject("BufferResourceCache");
            var res = obj.AddComponent<BufferResourceCache>();
            obj.transform.SetParent(BattleViewCtrl.GetInstance().transform);
            obj.transform.localPosition = Vector3.zero;
            obj.transform.localScale = Vector3.one;
            obj.transform.localEulerAngles = Vector3.zero;
            return res;
        }

        public static void UnInitialize(BufferResourceCache brc)
        {
            if (brc != null)
            {
                GameObject.Destroy(brc.gameObject);
            }
        }

        void Start()
        {
            loadedParticleCounter = new Dictionary<string, int>();
        }

        void Destroy()
        {
            StopAllCoroutines();
            foreach (var kvp in loadingParticleCounter)
            {
                RemoveBuffParticle(kvp.Key, kvp.Value);
            }
            foreach (var kvp in loadedParticleCounter)
            {
                RemoveBuffParticle(kvp.Key, kvp.Value);
            }
            loadedParticleCounter.Clear();
            loadingParticleCounter.Clear();
        }
    }
}
